HiSEN

线上事故记录 - 死锁

一、背景描述

在支付业务当中,每一笔交易都得进行记账。

两种情况:

  1. 第一步先冻结,交易成功,解冻并扣款(A账户->B账户->C账户);
  2. 第一步先冻结,交易失败,解冻并归还(A账户->B账户->A账户);

上面的两种情况各自都是在一个事物当中。

二、问题描述

在同一个商户进行并发操作的时候,交易有成功有失败;

  1. 成功的时候钱是:A账户->B账户;
  2. 失败的时候钱是:B账户->A账户;

因为在各自的事物当中更新两条记录的信息,并且使用了for update(innodb引擎)
ß
在某一瞬间:成功的先锁A账户,失败的先锁了B记录

接下来就两个事物各自持有对方想要的资源,并且不释放已经占有的资源,就造成了死锁

三、解决方法

在程序里面,更新两个账户的钱的时候,始终先更新ID更小的那条记录,那样不管多少个事务同时进来

都会按照固定的顺序去持有资源,比如先A再B,这样就不会出现各自持有对方想要的资源

1
2
3
ID ACCOUNT
10 A
11 B

每个事务都是先锁定A再锁定B,拿不到锁就一直等待